#include "stdafx.h"
#include "DeviceUtil.h"

#pragma comment (lib, "setupapi.lib")

USING_NS_UTILS

BOOL DeviceUtil::enableByClassGuidAndService(LPCGUID clssGuid, LPCTSTR service)
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(clssGuid, NULL, NULL, DIGCF_PRESENT);
	if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE;

	BOOL bResult = TRUE;
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD index = 0; SetupDiEnumDeviceInfo(hDevInfo, index, &deviceInfoData); index++)
	{
		TCHAR spdrpName[MAX_PATH] = { 0 };
		if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_SERVICE, NULL, (PBYTE)spdrpName, MAX_PATH, NULL)) continue;
		if (lstrcmpi(service, spdrpName) != 0) continue;

		if (!ChangeDeviceState(hDevInfo, &deviceInfoData, DICS_ENABLE))
			bResult = FALSE;
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
	return bResult;
}

BOOL DeviceUtil::disableByClassGuidAndService(LPCGUID clssGuid, LPCTSTR service)
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(clssGuid, NULL, NULL, DIGCF_PRESENT);
	if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE;

	BOOL bResult = TRUE;
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD index = 0; SetupDiEnumDeviceInfo(hDevInfo, index, &deviceInfoData); index++)
	{
		TCHAR spdrpName[MAX_PATH] = { 0 };
		if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_SERVICE, NULL, (PBYTE)spdrpName, MAX_PATH, NULL)) continue;
		if (lstrcmpi(service, spdrpName) != 0) continue;

		if (!ChangeDeviceState(hDevInfo, &deviceInfoData, DICS_DISABLE))
			bResult = FALSE;
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
	return bResult;
}

BOOL DeviceUtil::uninstallByClassGuidAndService(LPCGUID clssGuid, LPCTSTR service)
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(clssGuid, NULL, NULL, DIGCF_PRESENT);
	if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE;

	BOOL bResult = TRUE;
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD index = 0; SetupDiEnumDeviceInfo(hDevInfo, index, &deviceInfoData); index++)
	{
		TCHAR spdrpName[MAX_PATH] = { 0 };
		if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_SERVICE, NULL, (PBYTE)spdrpName, MAX_PATH, NULL)) continue;
		if (lstrcmpi(service, spdrpName) != 0) continue;
		if (!SetupDiRemoveDevice(hDevInfo, &deviceInfoData))
			bResult = FALSE;
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
	return bResult;
}

BOOL DeviceUtil::popupByClassGuidAndService(LPCGUID clssGuid, LPCTSTR service)
{
	return 0;
}

BOOL DeviceUtil::enableByClassGuidAndUpperFilters(LPCGUID clssGuid, LPCTSTR upperFilters)
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(clssGuid, NULL, NULL, DIGCF_PRESENT);
	if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE;

	BOOL bResult = TRUE;
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD index = 0; SetupDiEnumDeviceInfo(hDevInfo, index, &deviceInfoData); index++)
	{
		TCHAR spdrpName[MAX_PATH] = { 0 };
		if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_UPPERFILTERS, NULL, (PBYTE)spdrpName, MAX_PATH, NULL)) continue;
		if (lstrcmpi(upperFilters, spdrpName) != 0) continue;

		if (!ChangeDeviceState(hDevInfo, &deviceInfoData, DICS_ENABLE))
			bResult = FALSE;
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
	return bResult;
}

BOOL DeviceUtil::disableByClassGuidAndUpperFilters(LPCGUID clssGuid, LPCTSTR upperFilters)
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(clssGuid, NULL, NULL, DIGCF_PRESENT);
	if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE;

	BOOL bResult = TRUE;
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD index = 0; SetupDiEnumDeviceInfo(hDevInfo, index, &deviceInfoData); index++)
	{
		TCHAR spdrpName[MAX_PATH] = { 0 };
		if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_UPPERFILTERS, NULL, (PBYTE)spdrpName, MAX_PATH, NULL)) continue;
		if (lstrcmpi(upperFilters, spdrpName) != 0) continue;

		if (!ChangeDeviceState(hDevInfo, &deviceInfoData, DICS_DISABLE))
		{
			bResult = FALSE;
		}
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
	return bResult;
}

BOOL DeviceUtil::enableByClassGuidAndFriendlyName(LPCGUID clssGuid, LPCTSTR friendlyName)
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(clssGuid, NULL, NULL, DIGCF_PRESENT);
	if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE;

	BOOL bResult = TRUE;
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD index = 0; SetupDiEnumDeviceInfo(hDevInfo, index, &deviceInfoData); index++)
	{
		TCHAR spdrpName[MAX_PATH] = { 0 };
		if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)spdrpName, MAX_PATH, NULL)) continue;
		if (lstrstr(spdrpName, friendlyName) == 0) continue;

		if (!ChangeDeviceState(hDevInfo, &deviceInfoData, DICS_ENABLE))
			bResult = FALSE;
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
	return bResult;
}

BOOL DeviceUtil::disableByClassGuidAndFriendlyName(LPCGUID clssGuid, LPCTSTR friendlyName)
{
	HDEVINFO hDevInfo = SetupDiGetClassDevs(clssGuid, NULL, NULL, DIGCF_PRESENT);
	if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE;

	BOOL bResult = TRUE;
	SP_DEVINFO_DATA deviceInfoData;
	deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
	for (DWORD index = 0; SetupDiEnumDeviceInfo(hDevInfo, index, &deviceInfoData); index++)
	{
		TCHAR spdrpName[MAX_PATH] = { 0 };
		if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &deviceInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)spdrpName, MAX_PATH, NULL)) continue;
		if (lstrstr(spdrpName, friendlyName) == 0) continue;

		if (!ChangeDeviceState(hDevInfo, &deviceInfoData, DICS_DISABLE))
			bResult = FALSE;
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
	return bResult;
}

BOOL DeviceUtil::ChangeDeviceState(HDEVINFO hDevInfo, PSP_DEVINFO_DATA deviceInfoData, DWORD state)
{
	SP_PROPCHANGE_PARAMS propChange;
	propChange.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
	propChange.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
	propChange.Scope = DICS_FLAG_GLOBAL;
	propChange.StateChange = state;
	propChange.HwProfile = 0;

	if (!SetupDiSetClassInstallParams(hDevInfo, deviceInfoData, (SP_CLASSINSTALL_HEADER*)&propChange, sizeof(propChange))) return FALSE;

	return SetupDiChangeState(hDevInfo, deviceInfoData);
}
